/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package sqlserver;

import Database.Database;
import Database.DatabasesManager;
import Database.Table;
import java.awt.event.ActionEvent;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.AbstractAction;
import javax.swing.JOptionPane;
import javax.swing.JPopupMenu;
import javax.swing.JTabbedPane;
import javax.swing.JTree;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
import javax.swing.tree.DefaultMutableTreeNode;
import javax.swing.tree.DefaultTreeModel;
import javax.swing.tree.TreePath;

/**
 *
 * @author PHAMDANH
 */
public class ServerManager {
    private SQLServerMainForm mainForm;
    private SocketListener listener;
    private int port = 1234;    
    private JPopupMenu popup_tabbedPane;
    private JTabbedPane tabbedPane;    
    private DefaultMutableTreeNode server;
    private DefaultMutableTreeNode databasesNode;
    private DefaultMutableTreeNode connectedNode;
    private JTree tree;    
    private JPopupMenu popup_databases;
    private JPopupMenu popup_database;
    private JPopupMenu popup_tables;
    private JPopupMenu popup_table;
    private JPopupMenu popup_keys;
    private JPopupMenu popup_key;
    private List<Database> databases;
    private TreePath clickedPath;
    private InetAddress Address;
    private DatabasesManager databasesManager;    
    private int tableIdx = 0;
    private int databaseIdx = 0;
    ServerManager(SQLServerMainForm form)
    {
        mainForm = form;
        //Load list database
        databasesManager=new DatabasesManager();
        databasesManager.Load();
        databases = databasesManager.getDatabases();
        //Init tabbed pane
        tabbedPane = new JTabbedPane();
        popup_tabbedPane = new JPopupMenu();        
        tabbedPane.add(popup_tabbedPane);
        tabbedPane.addChangeListener(tabbedPaneChangeListener);
        tabbedPane.addMouseListener(new PopupTabbedPaneTrigger());  
        //Init tree view
        try 
        {
            Address = InetAddress.getLocalHost();
        } 
        catch (UnknownHostException ex) 
        {
            Logger.getLogger(SQLServerMainForm.class.getName()).log(Level.SEVERE, null, ex);
        }
        String serverName = Address.getHostName();
        server = new DefaultMutableTreeNode(serverName, true);
        databasesNode = new DefaultMutableTreeNode("Databases");      
        connectedNode = new DefaultMutableTreeNode("Connected user");      
        for(int i=0;i<databases.size();i++)
        {
            Database database= databases.get(i);
            List<Table> tables = database.getTable();
            DefaultMutableTreeNode databaseNode = new DefaultMutableTreeNode(database.getName());
            DefaultMutableTreeNode tablesNode = new DefaultMutableTreeNode("Tables");
            for(int j=0;j<tables.size();j++)
            {
                Table table = tables.get(j);
                DefaultMutableTreeNode tableNode= new DefaultMutableTreeNode(table.getName());
                DefaultMutableTreeNode keysNode = new DefaultMutableTreeNode("Keys"); 
                tableNode.add(keysNode);
                tablesNode.add(tableNode);
            }            
            databaseNode.add(tablesNode);
            databasesNode.add(databaseNode);
        }        
        server.add(databasesNode);        
        server.add(connectedNode); 
        tree = new JTree(server);
        tree.setCellRenderer(new MyTreeCellRenderer());        
        popup_databases = new JPopupMenu();        
        popup_databases.add(act_new_database);
        popup_databases.add(act_refresh);
        popup_database = new JPopupMenu();        
        popup_database.add(act_rename_database);
        popup_database.add(act_delete_database);                
        popup_database.add(act_refresh);
        
        popup_tables = new JPopupMenu();
        popup_tables.add(act_new_table);
        popup_tables.add(act_refresh);
        
        popup_table = new JPopupMenu();        
        popup_table.add(act_rename_table);
        popup_table.add(act_delete_table);
        popup_table.add(act_modify);
        popup_table.add(act_show_data);
        
        popup_keys = new JPopupMenu();
        popup_keys.add(act_refresh_key);        
        popup_key = new JPopupMenu();
        popup_key.add(act_delete_key);        
        
        tree.add(popup_databases);
        tree.add(popup_tables);
        tree.add(popup_table);
        tree.add(popup_keys);
        tree.add(popup_key);
        tree.addMouseListener(new PopupTreeViewTrigger());
        //Socket server
        listener = new SocketListener(port,this);
        listener.start();     
    }      
    public String getHostName()
    {
        return Address.getHostName();
    }
    public String getHostIP()
    {
        return Address.getHostAddress();
    }
    public int getPort()
    {
        return port;
    }
    public void Dispose()
    {
        listener.Dispose();
    }
    public JTabbedPane getTabbedPane()
    {
        return tabbedPane;
    }
    public void RefreshConnectedNode()
    {
        List<String> users = listener.getConnectedUser();
        connectedNode.removeAllChildren();
        for(int i=0;i<users.size();i++)
        {
            DefaultMutableTreeNode userNode= new DefaultMutableTreeNode(users.get(i));
            connectedNode.add(userNode);
        }
        ((DefaultTreeModel)tree.getModel()).reload();
        tree.expandPath(clickedPath);
    }
    public void RefreshKeysNode()
    {
        DefaultMutableTreeNode tempNode = (DefaultMutableTreeNode) clickedPath.getLastPathComponent();                    
        tempNode.removeAllChildren();
        tableIdx = tempNode.getParent().getParent().getIndex(tempNode.getParent());
        databaseIdx = databasesNode.getIndex(tempNode.getParent().getParent().getParent());
        Table tb = databases.get(databaseIdx).getTable().get(tableIdx);
        if(tb.getPrimaryKey()!=null)
        {
            DefaultMutableTreeNode pkNode = new DefaultMutableTreeNode(tb.getPrimaryKey().getName());
            tempNode.add(pkNode);
        }
        for(int i=0;i<tb.getForeignKey().size();i++)
        {
            DefaultMutableTreeNode fkNode = new DefaultMutableTreeNode(tb.getForeignKey().get(i).getName());
            tempNode.add(fkNode);
        }
        ((DefaultTreeModel)tree.getModel()).reload();
        TreePath path = new TreePath(tempNode.getPath());
        tree.expandPath(path);
    }
    
    private AbstractAction act_closeAll = new AbstractAction("Close all tab") 
    { 
        @Override
        public void actionPerformed(ActionEvent e)
        {
            int count = tabbedPane.getTabCount();
            for(int i=0;i<count;i++)               
                tabbedPane.remove(0);
        }
    };
    private AbstractAction act_close = new AbstractAction("Close tab") 
    { 
        @Override
        public void actionPerformed(ActionEvent e)
        {
            int tabIndex = tabbedPane.getSelectedIndex();               
            tabbedPane.remove(tabIndex);
        }
    };
    private ChangeListener tabbedPaneChangeListener = new ChangeListener() 
    {
        @Override
        public void stateChanged(ChangeEvent changeEvt) 
        {
            JTabbedPane temp = (JTabbedPane) changeEvt.getSource();
            int index = temp.getSelectedIndex();
            if(index<temp.getTabCount()&&index>=0)
            if(tabbedPane.getComponentAt(index).getClass()==ShowDataPanel.class)
            {
                ShowDataPanel panel = (ShowDataPanel) tabbedPane.getComponentAt(index);
                panel.InitTableModel();                
            }
        }
    };
    private class PopupTabbedPaneTrigger extends MouseAdapter
    {
        @Override
        public void mouseReleased(MouseEvent e)
        {            
            if (e.isPopupTrigger())
            {
                int x = e.getX();
                int y = e.getY();   
                popup_tabbedPane.removeAll();
                popup_tabbedPane.add(act_close);
                popup_tabbedPane.add(act_closeAll); 
                popup_tabbedPane.show(tabbedPane, x, y);
            }
            
        }
    }
    private AbstractAction act_new_database = new AbstractAction("New Database") 
    { 
        @Override
        public void actionPerformed(ActionEvent e)
        {
            String databaseName = JOptionPane.showInputDialog("Enter Database Name:");
            if (databaseName != null) 
            {
                if(!"".equals(databaseName)&&IsValidName(databaseName))
                {
                    if(databasesManager.IsExistDatabase(databaseName)==false)
                    {
                        DefaultMutableTreeNode databaseNode = new DefaultMutableTreeNode(databaseName);                                                
                        DefaultMutableTreeNode tablesNode = new DefaultMutableTreeNode("Tables");                                   
                        databaseNode.add(tablesNode);
                        databasesNode.add(databaseNode);
                        ((DefaultTreeModel)tree.getModel()).reload();
                        tree.expandPath(clickedPath);
                        Database database = new Database(databaseName);
                        databases.add(database);
                        mainForm.RefreshComboBoxCurrentDatabase();
                    }
                    else
                        JOptionPane.showMessageDialog(null, "Database đã tồn tại");   
                }
                else
                    JOptionPane.showMessageDialog(null, "Tên database không hợp lệ");   
            }            
        }
    };
    private AbstractAction act_rename_database = new AbstractAction("Rename Database") 
    {
        @Override
        public void actionPerformed(ActionEvent e)
        {
            String databaseName = JOptionPane.showInputDialog("Enter New Database Name:");
            if (databaseName != null) 
            {
                if(!"".equals(databaseName)&&IsValidName(databaseName))
                {
                    if(databasesManager.IsExistDatabase(databaseName)==false)
                    {
                        DefaultMutableTreeNode tempNode = (DefaultMutableTreeNode) clickedPath.getLastPathComponent();                    
                        databaseIdx = databasesNode.getIndex(tempNode);                        
                        tempNode.setUserObject(databaseName);
                        if(!databases.get(databaseIdx).Rename(databaseName))
                            JOptionPane.showMessageDialog(null, "Rename thất bại");  
                        ((DefaultTreeModel)tree.getModel()).reload();   
                        TreePath path = new TreePath(databasesNode.getPath());
                        tree.expandPath(path);       
                        mainForm.RefreshComboBoxCurrentDatabase();
                    }
                    else
                        JOptionPane.showMessageDialog(null, "Database đã tồn tại");   
                }
                else
                    JOptionPane.showMessageDialog(null, "Tên database không hợp lệ");   
            }            
        }
    };
    public boolean IsValidName(String name)
    {
        for(int i=0;i<name.length();i++)
        {
            char ch= name.charAt(i);
            if((ch>=97&&ch<=122)||(ch>=65&&ch<=90)||(ch>=48&&ch<=57)||ch==95)
                continue;
            else
                return false;
        }
        return true;
    }
    private AbstractAction act_delete_database = new AbstractAction("Delete Database") 
    { 
        @Override
        public void actionPerformed(ActionEvent e)
        {
            int value = JOptionPane.showConfirmDialog(tree, "Bạn có chắc muốn xóa database không?");            
            DefaultMutableTreeNode tempNode = (DefaultMutableTreeNode) clickedPath.getLastPathComponent();                    
            databaseIdx = databasesNode.getIndex(tempNode);
            if(value == 0)//yes
            {
                databasesNode.remove(databaseIdx);
                databases.get(databaseIdx).Delete();
                databases.remove(databaseIdx);                
                ((DefaultTreeModel)tree.getModel()).reload();
                TreePath path = new TreePath(databasesNode.getPath());
                tree.expandPath(path);
                mainForm.RefreshComboBoxCurrentDatabase();
            }
        }
    };
    private AbstractAction act_refresh_key = new AbstractAction("Refresh") 
    { 
        @Override
        public void actionPerformed(ActionEvent e)
        {
            RefreshKeysNode();
        }
    };
    private AbstractAction act_delete_key = new AbstractAction("Delete key") 
    { 
        @Override
        public void actionPerformed(ActionEvent e)
        {
            int value = JOptionPane.showConfirmDialog(tree, "Bạn có chắc muốn xóa khóa này không?");            
            DefaultMutableTreeNode tempNode = (DefaultMutableTreeNode) clickedPath.getLastPathComponent();                    
            databaseIdx = databasesNode.getIndex(tempNode.getParent().getParent().getParent().getParent());
            tableIdx = tempNode.getParent().getParent().getParent().getIndex(tempNode.getParent().getParent());            
            if(value == 0)//yes
            {                                
                int keyIdx =  tempNode.getParent().getIndex(tempNode);
                String keyName=tempNode.getUserObject().toString();
                if(keyName.charAt(0)!='p')//Khóa ngoại
                {
                    if(databases.get(databaseIdx).RemoveForeignKey(keyName,databases.get(databaseIdx).getTable().get(tableIdx).getName()))
                    {
                        TreePath path = new TreePath(((DefaultMutableTreeNode) tempNode.getParent()).getPath());
                        ((DefaultMutableTreeNode)tempNode.getParent()).remove(keyIdx);                       
                        ((DefaultTreeModel)tree.getModel()).reload();                
                        tree.expandPath(path);
                    }
                    else
                        JOptionPane.showMessageDialog(null, "Delete khóa ngoại không thành công"); 
                }     
                else
                {
                    if(databases.get(databaseIdx).RemovePrimaryKey(databases.get(databaseIdx).getTable().get(tableIdx).getName()))
                    {
                        TreePath path = new TreePath(((DefaultMutableTreeNode) tempNode.getParent()).getPath());
                        ((DefaultMutableTreeNode)tempNode.getParent()).remove(keyIdx);
                        ((DefaultTreeModel)tree.getModel()).reload();                
                        tree.expandPath(path);
                    }
                    else
                        JOptionPane.showMessageDialog(null, "Delete khóa chính không thành công"); 
                } 
            }
        }
    };
    private AbstractAction act_new_table= new AbstractAction("New Table") 
    { 
        @Override
        public void actionPerformed(ActionEvent e)
        {
            String tableName = JOptionPane.showInputDialog("Enter Table Name:");
            if (tableName != null) 
            {
                if(!"".equals(tableName)&&IsValidName(tableName))
                {
                    DefaultMutableTreeNode tempNode = (DefaultMutableTreeNode) clickedPath.getLastPathComponent();                    
                    databaseIdx = databasesNode.getIndex(tempNode.getParent());
                    if(databases.get(databaseIdx).IsExistTable(tableName)==false)
                    {
                        DefaultMutableTreeNode tableNode = new DefaultMutableTreeNode(tableName);                       
                        DefaultMutableTreeNode keysNode = new DefaultMutableTreeNode("Keys"); 
                        tableNode.add(keysNode);
                        tempNode.add(tableNode);
                        databases.get(databaseIdx).AddTable(tableName);
                        ((DefaultTreeModel)tree.getModel()).reload();                       
                        tree.expandPath(clickedPath);
                    }
                    else
                        JOptionPane.showMessageDialog(null, "Table đã tồn tại");   
                }
                else
                    JOptionPane.showMessageDialog(null, "Tên table không hợp lệ");   
            }   
        }
    };
    private AbstractAction act_rename_table= new AbstractAction("Rename Table") 
    { 
        @Override
        public void actionPerformed(ActionEvent e)
        {
            String tableName = JOptionPane.showInputDialog("Enter New Table Name:");
            if (tableName != null) 
            {
                if(!"".equals(tableName)&&IsValidName(tableName))
                {
                    DefaultMutableTreeNode tempNode = (DefaultMutableTreeNode) clickedPath.getLastPathComponent();                    
                    databaseIdx = databasesNode.getIndex(tempNode.getParent().getParent());
                    tableIdx = tempNode.getParent().getIndex(tempNode);
                    if(databases.get(databaseIdx).IsExistTable(tableName)==false)
                    {
                        tempNode.setUserObject(tableName);
                        databases.get(databaseIdx).getTable().get(tableIdx).setName(tableName);
                        ((DefaultTreeModel)tree.getModel()).reload();                       
                        TreePath path = new TreePath(((DefaultMutableTreeNode) tempNode.getParent()).getPath());
                        tree.expandPath(path);
                    }
                    else
                        JOptionPane.showMessageDialog(null, "Table đã tồn tại");   
                }
                else
                    JOptionPane.showMessageDialog(null, "Tên table không hợp lệ");   
            }   
        }
    };
    private AbstractAction act_delete_table= new AbstractAction("Delete Table") 
    { 
        @Override
        public void actionPerformed(ActionEvent e)
        {
            int value = JOptionPane.showConfirmDialog(tree, "Bạn có chắc muốn xóa table này không?");            
            DefaultMutableTreeNode tempNode = (DefaultMutableTreeNode) clickedPath.getLastPathComponent();                    
            databaseIdx = databasesNode.getIndex(tempNode.getParent().getParent());
            tableIdx = tempNode.getParent().getIndex(tempNode);
            if(value == 0)//yes
            {
                TreePath path = new TreePath(((DefaultMutableTreeNode) tempNode.getParent()).getPath());
                ((DefaultMutableTreeNode)tempNode.getParent()).remove(tableIdx);
                databases.get(databaseIdx).getTable().remove(tableIdx);
                ((DefaultTreeModel)tree.getModel()).reload();                
                tree.expandPath(path);
            }
        }
    };
    private AbstractAction act_refresh= new AbstractAction("Refresh") 
    { 
        @Override
        public void actionPerformed(ActionEvent e)
        {
            ((DefaultTreeModel)tree.getModel()).reload();
            tree.expandPath(clickedPath);
        }
    };
    private AbstractAction act_show_data= new AbstractAction("Show data") 
    { 
        @Override
        public void actionPerformed(ActionEvent e)
        {
            DefaultMutableTreeNode tempNode = (DefaultMutableTreeNode) clickedPath.getLastPathComponent();
            tableIdx = tempNode.getParent().getIndex(tempNode);
            databaseIdx = databasesNode.getIndex(tempNode.getParent().getParent());
            
            String tabName = databases.get(databaseIdx).getTable().get(tableIdx).getName()+" - Data";
            boolean isExist = false;
            int idx =-1;
            for(int i=0;i<tabbedPane.getTabCount();i++)
            {
                String temp = tabbedPane.getTitleAt(i);
                if(temp.equals(tabName))
                {                    
                    idx = i;
                    isExist = true;
                    break;
                }
            }
            if(isExist)
            {                               
                ShowDataPanel panel = (ShowDataPanel) tabbedPane.getComponentAt(idx);
                panel.InitTableModel();  
                tabbedPane.setSelectedIndex(idx);
            }   
            else                
                if(databases.get(databaseIdx).getTable().get(tableIdx).getColumns().size()>0)
                {
                    ShowDataPanel panel = new ShowDataPanel(databases.get(databaseIdx),databases.get(databaseIdx).getTable().get(tableIdx));
                    tabbedPane.addTab(tabName, panel);
                    tabbedPane.setSelectedIndex(tabbedPane.getTabCount()-1);
                    panel.InitTableModel();  
                }
                else
                    JOptionPane.showMessageDialog(null, "Table chưa có column");            
        }
    };
    private AbstractAction act_modify= new AbstractAction("Modify") 
    { 
        @Override
        public void actionPerformed(ActionEvent e)
        {            
            DefaultMutableTreeNode tempNode = (DefaultMutableTreeNode) clickedPath.getLastPathComponent();
            tableIdx = tempNode.getParent().getIndex(tempNode);
            databaseIdx = databasesNode.getIndex(tempNode.getParent().getParent());
            
            String tabName = databases.get(databaseIdx).getTable().get(tableIdx).getName()+" - Modify";
            boolean isExist = false;
            int idx =-1;
            for(int i=0;i<tabbedPane.getTabCount();i++)
            {
                String temp = tabbedPane.getTitleAt(i);
                if(temp.equals(tabName))
                {                    
                    idx = i;
                    isExist = true;
                    break;
                }
            }
            if(isExist)
                tabbedPane.setSelectedIndex(idx);
            else
            {
                ModifyPanel panel = new ModifyPanel(databases.get(databaseIdx),databases.get(databaseIdx).getTable().get(tableIdx));
                tabbedPane.addTab(tabName, panel);            
                tabbedPane.setSelectedIndex(tabbedPane.getTabCount()-1);
            }
        }
    };
    public JTree getTree()
    {
        return tree;
    }
    private class PopupTreeViewTrigger extends MouseAdapter
    {
        @Override
        public void mouseReleased(MouseEvent e)
        {
            if (e.isPopupTrigger())
            {
                int x = e.getX();
                int y = e.getY();                
                TreePath path = tree.getPathForLocation(x, y);
                if (path != null)
                {
                    DefaultMutableTreeNode tempNode = (DefaultMutableTreeNode)path.getLastPathComponent();
                    tree.setSelectionPath(path);
                    int level = tempNode.getLevel();
                    switch(level)
                    {
                        case 1:
                            popup_databases.show(tree, x, y);
                            break;
                        case 2:
                            popup_database.show(tree, x, y);
                            break;
                        case 3:
                            popup_tables.show(tree, x, y);
                            break;
                        case 4:
                            popup_table.show(tree, x, y);
                            break;
                        case 5:
                            popup_keys.show(tree, x, y);
                            break;
                        case 6:
                            popup_key.show(tree, x, y);
                            break;
                        default:
                            break;
                    }
                    clickedPath = path;
                }
            }
        }
    }
    public DatabasesManager getDatabasesManager()
    {
        return databasesManager;
    }
}
